﻿//------------------------------------------------------------------------------
// Copyright © FRA & FV 2014
// All rights reserved
//------------------------------------------------------------------------------
// Binary Serialization SDK
//
// SVN revision information:
//   $Revision: 98 $
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace FRAFV.Binary.Serialization
{
	/// <summary>
	/// Specifies various formats serializable data.
	/// </summary>
	public enum BinFormat
	{
		/// <summary>Represents automatic type detection by the property declaration.</summary>
		Auto,
		/// <summary>Represents an 8-bit (1 byte) signed integer. This format is automatically mapped by a <see cref="T:System.SByte"/>
		///   property declaration.</summary>
		Int8,
		/// <summary>Represents a 16-bit (2 bytes) signed integer. This format is automatically mapped by a <see cref="T:System.Int16"/>
		///   property declaration.</summary>
		Int16,
		/// <summary>Represents a 24-bit (3 bytes) signed integer. This format isn't usable for automatic type detection.</summary>
		Int24,
		/// <summary>Represents a 32-bit (4 bytes) signed integer. This format is automatically mapped by an <see cref="T:System.Int32"/>
		///   property declaration.</summary>
		Int32,
		/// <summary>Represents a 64-bit (8 bytes) signed integer. This format is automatically mapped by an <see cref="T:System.Int64"/>
		///   property declaration.</summary>
		Int64,
		/// <summary>Represents an 8-bit (1 byte) unsigned integer. This format is automatically mapped by a <see cref="T:System.Byte"/>
		///   property declaration.</summary>
		UInt8,
		/// <summary>Represents a 16-bit (2 bytes) unsigned integer. This format is automatically mapped by an <see cref="T:System.UInt16"/>
		///   property declaration.</summary>
		UInt16,
		/// <summary>Represents a 24-bit (3 bytes) unsigned integer. This format isn't usable for automatic type detection.</summary>
		/// <remarks>This data format is usable with <see cref="T:FRAFV.Binary.Serialization.BinReader"/> only.</remarks>
		UInt24,
		/// <summary>Represents a 32-bit (4 bytes) unsigned integer. This format is automatically mapped by an <see cref="T:System.UInt32"/>
		///   property declaration.</summary>
		UInt32,
		/// <summary>Represents a 64-bit (8 bytes) unsigned integer. This format is automatically mapped by an <see cref="T:System.UInt64"/>
		///   property declaration.</summary>
		UInt64,
		/// <summary>Represents a 14-bit unsigned integer in synchsafe format. This format isn't usable for automatic
		///   type detection.</summary>
		/// <remarks>
		/// Synchsafe integers usage can never be any false synchs. Synchsafe integers are integers that keep its
		/// highest bit (bit 7) zeroed, making seven bits out of eight available. Thus a 16 bit synchsafe integer can
		/// store 14 bits of information.
		/// </remarks>
		SynchSafeInt16,
		/// <summary>Represents a 28-bit unsigned integer in synchsafe format. This format isn't usable for automatic
		///   type detection.</summary>
		/// <remarks>
		/// Synchsafe integers usage can never be any false synchs. Synchsafe integers are integers that keep its
		/// highest bit (bit 7) zeroed, making seven bits out of eight available. Thus a 32 bit synchsafe integer can
		/// store 28 bits of information.
		/// </remarks>
		SynchSafeInt32,
		/// <summary>Represents a 56-bit unsigned integer in synchsafe format. This format isn't usable for automatic
		///   type detection.</summary>
		/// <remarks>
		/// Synchsafe integers usage can never be any false synchs. Synchsafe integers are integers that keep its
		/// highest bit (bit 7) zeroed, making seven bits out of eight available. Thus a 64 bit synchsafe integer can
		/// store 56 bits of information.
		/// </remarks>
		SynchSafeInt64,
		/// <summary>Represents a Boolean value as an 4-byte integer value.
		///   The value <c>1</c> represents <see langword="true"/> and <c>0</c> represents <see langword="false"/>.
		///   This format isn't usable for automatic type detection.</summary>
		Bool,
		/// <summary>Represents a Boolean value as an 1-byte integer value.
		///   The value <c>1</c> represents <see langword="true"/> and <c>0</c> represents <see langword="false"/>.
		///   This format automatic maps to <see cref="T:System.Boolean"/> property declaration.</summary>
		Bit,
		/// <summary>Represents a Boolean value as an 2-byte integer value.
		///   The value <c>-1</c> represents <see langword="true"/> and <c>0</c> represents <see langword="false"/>.
		///   This format isn't usable for automatic type detection.</summary>
		/// <remarks>This is the default format of a Boolean parameter in COM calls.</remarks>
		VariantBool,
		/// <summary>Represents a 32-bit single-precision floating-point number.
		///   This format is automatically mapped by a <see cref="T:System.Single"/> property declaration.</summary>
		Float,
		/// <summary>Represents a 64-bit double-precision floating-point number.
		///   This format is automatically mapped by a <see cref="T:System.Double"/> property declaration.</summary>
		Double,
		/// <summary>Represents a date as a 62-bit value indicating the number of
		///   100-nanosecond intervals since January 1, 0001 in the Gregorian calendar.</summary>
		Date,
		/// <summary>Represents a UNIX date as a 32-bit signed value indicating the number of
		///   seconds since midnight January 1, 1970 in the Gregorian calendar.</summary>
		UNIXDateI32,
		/// <summary>Represents a UNIX date as an 32-bit unsigned value indicating the number of
		///   seconds since midnight January 1, 1970 in the Gregorian calendar.</summary>
		UNIXDateU32,
		/// <summary>Represents a UNIX date as a 64-bit value indicating the number of
		///   seconds since midnight January 1, 1970 in the Gregorian calendar.</summary>
		UNIXDate64,
		/// <summary>Represents a Macintosh date as a 32-bit value indicating the number of
		///   seconds since midnight January 1, 1904 in the Gregorian calendar.</summary>
		/// <para>Macintosh date format: a 32-bit value indicating the number of seconds that have passed since
		/// midnight January 1, 1904.</para>
		/// <para>This value does not specify a time zone. Common practice is to use local time for
		/// the time zone where the value is generated.</para>
		/// <para>It is strongly recommended that all calendar date and time values be stored using UTC time,
		/// so that all files have a time and date relative to the same time zone.</para>
		MacDate32,
		/// <summary>Represents a Macintosh date as an 64-bit value indicating the number of
		///   seconds since midnight January 1, 1904 in the Gregorian calendar.</summary>
		/// <remarks>
		/// <para>Macintosh date format: a 64-bit value indicating the number of seconds that have passed since
		/// midnight January 1, 1904.</para>
		/// <para>This value does not specify a time zone. Common practice is to use local time for
		/// the time zone where the value is generated.</para>
		/// <para>It is strongly recommended that all calendar date and time values be stored using UTC time,
		/// so that all files have a time and date relative to the same time zone.</para>
		/// </remarks>
		MacDate64,
		/// <summary>Represents an OLE Automation date as an 64-bit floating-point value indicating the number of
		///   days since midnight December 31, 1899 in the Gregorian calendar.</summary>
		OLEDate,
		/// <summary>Represents a Windows file time as an 64-bit value indicating the number of
		///   100-nanosecond intervals since January 1, 1601 in the Gregorian calendar.</summary>
		FileTime,
		/// <summary>Represents a stream of binary data. This format is automatically mapped by an <see cref="T:Syste.Array"/>
		///   of type <see cref="T:Syste.Byte"/> property declaration.</summary>
		Binary,
		/// <summary>Represents a null-terminated character string. This format is automatically mapped by a <see cref="T:System.String"/>
		///   property declaration.</summary>
		CString,
		/// <summary>Represents a string value with fixed length. This format is automatically mapped by an <see cref="T:Syste.Array"/>
		///   of type <see cref="T:Syste.Char"/> property declaration.</summary>
		PString,
		/// <summary>Represents a character. This format is automatically mapped by a <see cref="T:System.Char"/>
		///   property declaration.</summary>
		Char,
	}

	/// <summary>
	/// Specifies various method declarations serialization code.
	/// </summary>
	public enum BinMethodMode
	{
		/// <summary>Inherits method declaration mode from parent block. This is default value for inner classes.</summary>
		Inherit,
		/// <summary>Represents <c>public virtual</c> method declaration. This declaration is automatically set
		///   for classes with no deriving or classes implemented <see cref="T:FRAFV.Binary.Serialization.IBinSerializable"/>
		///   interface.</summary>
		Virtual,
		/// <summary>Represents <c>public override</c> method declaration from virtual base method. This declaration
		///   is automatically set for derived classes. This is default value for root classes.</summary>
		Override,
		/// <summary>Represents final <c>public</c> method declaration. This declaration is automatically set
		///   for sealed classes with no deriving or sealed classes implemented <see cref="T:FRAFV.Binary.Serialization.IBinSerializable"/>
		///   interface.</summary>
		Final,
		/// <summary>Represents <c>public override</c> method declaration from abstract base method.</summary>
		Abstract,
	}

	/// <summary>
	/// Specifies various order kind of the items serialization code.
	/// </summary>
	public enum BinItemOrder
	{
		/// <summary>Inherits order kind from parent block. This is default value for inner classes.</summary>
		Inherit,
		/// <summary>Represents a sequence of items. This is default order kind for root classes.</summary>
		Sequence,
		/// <summary>Represents an item of choice.</summary>
		Choice,
		/// <summary>Represents items in any order.</summary>
		Any
	}

	/// <summary>
	/// Specifies various items usage in a binary block.
	/// </summary>
	public enum BinItemUsage
	{
		/// <summary>Represents an optional item.</summary>
		Optional,
		/// <summary>Represents a required item. An empty item will be created in the generated code
		/// if it isn't in serialized data.</summary>
		Required,
		/// <summary>Represents a series of items. Containing property or field should be of an array type
		/// or a collection type.</summary>
		Repeatable
	}

	/// <summary>Specifies that the <see cref="T:FRAFV.Binary.Serialization.BinSerializer" /> must serialize
	///   a particular class member as an array of binary datas.</summary>
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
	public class BinArrayAttribute : Attribute
	{
		/// <summary>Gets or sets the array items count serialization format. Only if a custom method in <see cref="P:FRAFV.Binary.Serialization.BinArrayAttribute.CountCustomMethod"/>
		///   property isn't specified, by default is single byte or inherted value from
		///   <see cref="T:FRAFV.Binary.Serialization.BinBlockAttribute" /> attribute.</summary>
		/// <returns>The array items count serialization format.</returns>
		/// <remarks>Default value for this property will be ignored if a custom method in <see cref="P:FRAFV.Binary.Serialization.BinArrayAttribute.CountCustomMethod"/>
		///   property is specified. In that case the property should be explicitly specified.</remarks>
		[DefaultValue(BinFormat.UInt8)]
		public BinFormat CountFormat { get; set; }

		/// <summary>Gets or sets the name of the custom method for array items count calculation. This property for
		///   read items count calculation if there is no data length format. This one for write calculated items count
		///   if items count format is explicitly specified. By default is <c>"index &lt; count"</c>.</summary>
		/// <returns>The name of the custom method for array items count calculation.</returns>
		/// <remarks>This property will be used for read items count calculation if items count format in <see cref="P:FRAFV.Binary.Serialization.BinArrayAttribute.CountFormat"/>
		///   property isn't specified. This one will be used for write calculated items count if items count format
		///   is explicitly specified. If this property specified as numeric value and items count format isn't specified,
		///   all serializaton methods will use this numeric value.</remarks>
		public string CountCustomMethod { get; set; }

		/// <summary>Gets or sets the condition expression for array items reading. By default is <c>"index &lt; count"</c>.</summary>
		/// <returns>The condition expression for array items reading.</returns>
		/// <remarks>This condition expression will be used for read items while reading. Other properties
		///   aren't allowed while this property is specified.</remarks>
		public string ConditionCustomMethod { get; set; }

		/// <summary>Initializes a new instance of the <see cref="T:FRAFV.Binary.Serialization.BinArrayAttribute" /> class.</summary>
		public BinArrayAttribute() { }

		/// <summary>Returns a string that represents the current attribute declaration.</summary>
		/// <returns>A string that represents the current attribute declaration.</returns>
		public override string ToString()
		{
			var args = new List<string>();
			if (this.CountFormat != BinFormat.Auto)
				args.Add("CountFormat=BinFormat." + this.CountFormat);
			if (this.CountCustomMethod != null)
				args.Add("CountCustomMethod=\"" + this.CountCustomMethod + "\"");
			if (this.ConditionCustomMethod != null)
				args.Add("ConditionCustomMethod=\"" + this.ConditionCustomMethod + "\"");
			return "[BinArray(" + String.Join(", ", args) + ")]";
		}
	}

	/// <summary>Specifies the derived types that the <see cref="T:FRAFV.Binary.Serialization.BinSerializer" /> can
	///   place in a serialized array.</summary>
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
	public class BinArrayItemAttribute : Attribute
	{
		/// <summary>Gets or sets the type allowed in an array. By default a item type will be detected by
		///   an array declaration. In that case it is usable for simple array and generic collection declarations.</summary>
		/// <returns>A type that is allowed in the array.</returns>
		public Type ItemType { get; set; }

		/// <summary>Gets or sets the name of the custom method for array item creation. By default is
		///   <c>"new ItemType()"</c>.</summary>
		/// <returns>The name of the custom method for array item creation.</returns>
		/// <remarks>If this property is specified then data length format in <see cref="P:FRAFV.Binary.Serialization.BinArrayAttribute.CountFormat"/>
		/// property will be ignored.</remarks>
		public string CreateCustomMethod { get; set; }

		/// <summary>Initializes a new instance of the <see cref="T:FRAFV.Binary.Serialization.BinArrayItemAttribute" /> class.</summary>
		public BinArrayItemAttribute() { }

		/// <summary>Returns a string that represents the current attribute declaration.</summary>
		/// <returns>A string that represents the current attribute declaration.</returns>
		public override string ToString()
		{
			var args = new List<string>();
			if (this.ItemType != null)
				args.Add("ItemType=typeof(" + this.ItemType.FullName + ")");
			if (this.CreateCustomMethod != null)
				args.Add("CreateCustomMethod=\"" + this.CreateCustomMethod + "\"");
			return "[BinArrayItem(" + String.Join(", ", args) + ")]";
		}
	}

	/// <summary>Indicates that a public field or property represents a binary data when the <see cref="T:FRAFV.Binary.Serialization.BinSerializer" />
	/// serializes or deserializes the object that contains it.</summary>
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]
	public class BinDataAttribute : Attribute
	{
		/// <summary>Gets or sets the format of the binary data serialization.</summary>
		/// <returns>The format of the binary block serialization.</returns>
		[DefaultValue(BinFormat.Auto)]
		public BinFormat Format { get; set; }

		/// <summary>Gets or sets the condition expression that returns the indication of data serialization.</summary>
		/// <returns>The condition expression that returns boolean value.</returns>
		public string Condition { get; set; }

		/// <summary>Gets or sets the data length serialization format. Only if a custom method in <see cref="P:FRAFV.Binary.Serialization.BinDataAttribute.LengthCustomMethod"/>
		///   property isn't specified, by default is single byte or inherted value from
		///   <see cref="T:FRAFV.Binary.Serialization.BinBlockAttribute" /> attribute.</summary>
		/// <returns>The data length serialization format.</returns>
		/// <remarks>The data length is usable for <see cref="F:FRAFV.Binary.Serialization.BinFormat.CString"/>,
		///   <see cref="F:FRAFV.Binary.Serialization.BinFormat.PString"/> and <see cref="F:FRAFV.Binary.Serialization.BinFormat.Binary"/>
		///   formats only in <see cref="P:FRAFV.Binary.Serialization.BinDataAttribute.Format"/> property. Default
		///   value for this property will be ignored if a custom method in <see cref="P:FRAFV.Binary.Serialization.BinDataAttribute.LengthCustomMethod"/>
		///   property is specified. In that case the property should be explicitly specified.</remarks>
		[DefaultValue(BinFormat.UInt8)]
		public BinFormat LengthFormat { get; set; }

		/// <summary>Gets or sets the name of the custom method for data length calculation. This property for
		///   read data length calculation if there is no data length format. This one for write calculated data length
		///   if data length format is explicitly specified.</summary>
		/// <returns>The name of the custom method for data length calculation.</returns>
		/// <remarks>The data length is usable for <see cref="F:FRAFV.Binary.Serialization.BinFormat.CString"/>,
		/// <see cref="F:FRAFV.Binary.Serialization.BinFormat.PString"/> and <see cref="F:FRAFV.Binary.Serialization.BinFormat.Binary"/>
		/// formats only in <see cref="P:FRAFV.Binary.Serialization.BinDataAttribute.Format"/> property. This property
		///   will be used for read data length calculation if data length format in <see cref="P:FRAFV.Binary.Serialization.BinDataAttribute.LengthFormat"/>
		///   property isn't specified. This one will be used for write calculated data length if data length format
		///   is explicitly specified. If this property specified as numeric value and data length format isn't specified,
		///   all serializaton methods will use this numeric value.</remarks>
		public string LengthCustomMethod { get; set; }

		/// <summary>Initializes a new instance of the <see cref="T:FRAFV.Binary.Serialization.BinDataAttribute" /> class.</summary>
		public BinDataAttribute() { }

		/// <summary>Initializes a new instance of the <see cref="T:FRAFV.Binary.Serialization.BinDataAttribute" /> class.</summary>
		/// <param name="format">The format of the binary block serialization.</param>
		public BinDataAttribute(BinFormat format)
		{
			this.Format = format;
		}

		/// <summary>Returns a string that represents the current attribute declaration.</summary>
		/// <returns>A string that represents the current attribute declaration.</returns>
		public override string ToString()
		{
			var args = new List<string>();
			if (this.Format != BinFormat.Auto)
				args.Add("BinFormat." + this.Format);
			if (this.Condition != null)
				args.Add("Condition=\"" + this.Condition + "\"");
			if (this.LengthFormat != BinFormat.Auto)
				args.Add("LengthFormat=BinFormat." + this.LengthFormat);
			if (this.LengthCustomMethod != null)
				args.Add("LengthCustomMethod=\"" + this.LengthCustomMethod + "\"");
			return "[BinData(" + String.Join(", ", args) + ")]";
		}
	}

	/// <summary>Indicates that a public field or property has custom methods for serialization or deserialization
	/// the object that contains it.</summary>
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
	public class BinCustomAttribute : Attribute
	{
		/// <summary>Gets or sets the expression of the custom deserialization. By default is <c>"Read_Property(reader)"</c> value.</summary>
		/// <returns>The expression of the custom deserialization.</returns>
		/// <seealso cref="M:FRAFV.Binary.Serialization.IBinSerializable.ReadBinary"/>
		public string ReadMethod { get; set; }

		/// <summary>Gets or sets the expression of the custom serialization. By default is <c>"Write_Property(writer)"</c> value.</summary>
		/// <returns>The expression of the custom serialization.</returns>
		/// <seealso cref="M:FRAFV.Binary.Serialization.IBinSerializable.WriteBinary"/>
		public string WriteMethod { get; set; }

		/// <summary>Gets or sets the expression of the custom data size calculation. By default is <c>"Size_Property()"</c> value.</summary>
		/// <returns>The expression of the custom data size calculation.</returns>
		/// <seealso cref="M:FRAFV.Binary.Serialization.IBinSerializable.DataSize"/>
		public string GetDataSizeMethod { get; set; }

		/// <summary>Initializes a new instance of the <see cref="T:FRAFV.Binary.Serialization.BinCustomAttribute" /> class.</summary>
		public BinCustomAttribute() { }

		/// <summary>Initializes a new instance of the <see cref="T:FRAFV.Binary.Serialization.BinCustomAttribute" /> class.</summary>
		/// <param name="readMethod">The name of the custom deserialization method.</param>
		/// <param name="getDataSizeMethod">The name of the custom method for data size calculation.</param>
		/// <param name="writeMethod">The name of the custom serialization method.</param>
		public BinCustomAttribute(string readMethod, string getDataSizeMethod, string writeMethod)
		{
			this.ReadMethod = readMethod;
			this.GetDataSizeMethod = getDataSizeMethod;
			this.WriteMethod = writeMethod;
		}

		/// <summary>Returns a string that represents the current attribute declaration.</summary>
		/// <returns>A string that represents the current attribute declaration.</returns>
		public override string ToString()
		{
			var args = new List<string>();
			if (this.ReadMethod != null)
				args.Add("ReadMethod=\"" + this.ReadMethod + "\"");
			if (this.GetDataSizeMethod != null)
				args.Add("GetDataSizeMethod=\"" + this.GetDataSizeMethod + "\"");
			if (this.WriteMethod != null)
				args.Add("WriteMethod=\"" + this.WriteMethod + "\"");
			return "[BinCustom(" + String.Join(", ", args) + ")]";
		}
	}

	/// <summary>Indicates that a public field or property represents a binary item (inner binary block) when
	/// the <see cref="T:FRAFV.Binary.Serialization.BinSerializer" /> serializes or deserializes the object that
	/// contains it.</summary>
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]
	public class BinItemAttribute : Attribute
	{
		/// <summary>Gets or sets the item usage in binary block. By default is optional usage.</summary>
		/// <returns>The item usage.</returns>
		public BinItemUsage ItemUsage { get; set; }

		/// <summary>Gets or sets the item type. By default the item type will be detected by
		///   a property or an array declaration. For array case it is usable for simple array and generic collection
		///   declarations.</summary>
		/// <returns>The item type.</returns>
		public Type ItemType { get; set; }

		/// <summary>Gets or sets the condition expression that returns the indication of item serialization.</summary>
		/// <returns>The condition expression that returns boolean value.</returns>
		public string Condition { get; set; }

		/// <summary>Initializes a new instance of the <see cref="T:FRAFV.Binary.Serialization.BinItemAttribute" /> class.</summary>
		/// <param name="usage">The item usage.</param>
		public BinItemAttribute(BinItemUsage usage)
		{
			this.ItemUsage = usage;
		}

		/// <summary>Initializes a new instance of the <see cref="T:FRAFV.Binary.Serialization.BinItemAttribute" /> class.</summary>
		public BinItemAttribute()
		{
			this.ItemUsage = BinItemUsage.Optional;
		}

		/// <summary>Returns a string that represents the current attribute declaration.</summary>
		/// <returns>A string that represents the current attribute declaration.</returns>
		public override string ToString()
		{
			var args = new List<string>();
			if (this.ItemUsage != BinItemUsage.Optional)
				args.Add("BinItemUsage." + this.ItemUsage);
			if (this.ItemType != null)
				args.Add("ItemType=typeof(" + this.ItemType.FullName + ")");
			if (this.Condition != null)
				args.Add("Condition=\"" + this.Condition + "\"");
			return "[BinItem(" + String.Join(", ", args) + ")]";
		}
	}

	/// <summary>Controls binary serialization of the attribute target as an binary data block.</summary>
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false)]
	public class BinBlockAttribute : Attribute
	{
		/// <summary>Gets or set the method declarations serialization code. By default is virtual declaration or
		/// inherited from parent class.</summary>
		/// <returns>The method declarations serialization code.</returns>
		[DefaultValue(BinMethodMode.Virtual)]
		public BinMethodMode MethodMode { get; set; }

		/// <summary>Gets or sets the name of string encoding.</summary>
		/// <returns>The name of string encoding.</returns>
		/// <remarks>If this property is specified then the custom method in <see cref="P:FRAFV.Binary.Serialization.BinBlockAttribute.EncodingCustomMethod"/>
		/// property will be ignored.</remarks>
		public string Encoding { get; set; }

		/// <summary>Gets or sets the data length serialization format. By default is single byte or inherted
		/// value from parent class.</summary>
		/// <returns>The data length serialization format.</returns>
		[DefaultValue(BinFormat.UInt8)]
		public BinFormat LengthFormat { get; set; }

		/// <summary>Gets or sets the name of a custom method for string encoding resolving.</summary>
		/// <returns>The name of a custom method for string encoding resolving.</returns>
		/// <remarks>This property will be ignored if string encoding in <see cref="P:FRAFV.Binary.Serialization.BinBlockAttribute.Encoding"/>
		/// property is specified.</remarks>
		public string EncodingCustomMethod { get; set; }

		/// <summary>Gets or sets the array items count serialization format. By default is single byte or inherted value
		/// from parent class.</summary>
		/// <returns>The array items count serialization format.</returns>
		[DefaultValue(BinFormat.UInt8)]
		public BinFormat CountFormat { get; set; }

		/// <summary>Gets or sets the type of <see cref="T:System.IO.BinaryReader"/> implementation. By default is
		/// inherted type from parent class.</summary>
		/// <returns>The type of <see cref="T:System.IO.BinaryReader"/> implementation.</returns>
		[DefaultValue("System.IO.BinaryReader")]
		public Type BinaryReaderType { get; set; }

		/// <summary>Gets or sets the type of <see cref="T:System.IO.BinaryWriter"/> implementation. By default is
		/// inherted type from parent class.</summary>
		/// <returns>The type of <see cref="T:System.IO.BinaryWriter"/> implementation.</returns>
		[DefaultValue("System.IO.BinaryWriter")]
		public Type BinaryWriterType { get; set; }

		/// <summary>Gets or sets the expression for executing before other deserialization. It isn't inherited.</summary>
		/// <returns>The expression for executing before other deserialization.</returns>
		public string ReadMethod { get; set; }

		/// <summary>Gets or sets the expression for executing before other serialization. It isn't inherited.</summary>
		/// <returns>The expression for executing before other serialization.</returns>
		/// <seealso cref="M:FRAFV.Binary.Serialization.WriteBinary"/>
		public string WriteMethod { get; set; }

		/// <summary>Gets or sets the expression for executing before data size calculation. It isn't inherited.</summary>
		/// <returns>The expression for executing before data size calculation.</returns>
		/// <seealso cref="M:FRAFV.Binary.Serialization.DataSize"/>
		public string GetDataSizeMethod { get; set; }

		/// <summary>Gets or sets the order kind in which items are serialized or deserialized. By default is
		/// a sequence of items order kind or inherted expression from parent class.</summary>
		/// <returns>The order kind of items code generation.</returns>
		public BinItemOrder ItemOrder { get; set; }

		/// <summary>Gets or sets the expression of the item deserialization. By default is
		/// <c>"new Item().ReadBinary(reader)"</c> value or inherted expression from parent class.</summary>
		/// <returns>The expression of the item deserialization.</returns>
		/// <seealso cref="M:FRAFV.Binary.Serialization.IBinSerializable.ReadBinary"/>
		public string ReadItemMethod { get; set; }

		/// <summary>Gets or sets the expression of the item serialization. By default is
		/// <c>"item.WriteBinary(writer)"</c> value or inherted expression from parent class.</summary>
		/// <returns>The expression of the item serialization.</returns>
		/// <seealso cref="M:FRAFV.Binary.Serialization.IBinSerializable.WriteBinary"/>
		public string WriteItemMethod { get; set; }

		/// <summary>Gets or sets the expression of the item data size calculation. By default is
		/// <c>"item.DataSize"</c> value or inherted expression from parent class.</summary>
		/// <returns>The expression of the item data size calculation.</returns>
		/// <seealso cref="M:FRAFV.Binary.Serialization.IBinSerializable.DataSize"/>
		public string GetItemSizeMethod { get; set; }

		/// <summary>Initializes a new instance of the <see cref="T:FRAFV.Binary.Serialization.BinBlockAttribute" /> class.</summary>
		public BinBlockAttribute() { }

		/// <summary>Inherits a new instance of the <see cref="T:FRAFV.Binary.Serialization.BinBlockAttribute" /> class.</summary>
		/// <param name="parent">Parent attribute.</param>
		public BinBlockAttribute(BinBlockAttribute parent)
		{
			this.MethodMode = parent.MethodMode;
			this.Encoding = parent.Encoding;
			this.LengthFormat = parent.LengthFormat;
			this.EncodingCustomMethod = parent.EncodingCustomMethod;
			this.CountFormat = parent.CountFormat;
			this.BinaryReaderType = parent.BinaryReaderType;
			this.BinaryWriterType = parent.BinaryWriterType;
			this.ReadMethod = parent.ReadMethod;
			this.WriteMethod = parent.WriteMethod;
			this.GetDataSizeMethod = parent.GetDataSizeMethod;
			this.ItemOrder = parent.ItemOrder;
			this.ReadItemMethod = parent.ReadItemMethod;
			this.WriteItemMethod = parent.WriteItemMethod;
			this.GetItemSizeMethod = parent.GetItemSizeMethod;
		}

		/// <summary>Returns a string that represents the current attribute declaration.</summary>
		/// <returns>A string that represents the current attribute declaration.</returns>
		public override string ToString()
		{
			var args = new List<string>();
			if (this.MethodMode != BinMethodMode.Inherit)
				args.Add("MethodMode=BinMethodMode." + this.MethodMode);
			if (this.Encoding != null)
				args.Add("Encoding=\"" + this.Encoding + "\"");
			if (this.LengthFormat != BinFormat.Auto)
				args.Add("LengthFormat=BinFormat." + this.LengthFormat);
			if (this.EncodingCustomMethod != null)
				args.Add("EncodingCustomMethod=\"" + this.EncodingCustomMethod + "\"");
			if (this.BinaryReaderType != null)
				args.Add("BinaryReaderType=typeof(" + this.BinaryReaderType.FullName + ")");
			if (this.BinaryWriterType != null)
				args.Add("BinaryWriterType=typeof(" + this.BinaryWriterType.FullName + ")");
			if (this.ReadMethod != null)
				args.Add("ReadMethod=\"" + this.ReadMethod + "\"");
			if (this.GetDataSizeMethod != null)
				args.Add("GetDataSizeMethod=\"" + this.GetDataSizeMethod + "\"");
			if (this.WriteMethod != null)
				args.Add("WriteMethod=\"" + this.WriteMethod + "\"");
			if (this.ItemOrder != BinItemOrder.Inherit)
				args.Add("ItemOrder=BinItemOrder." + this.ItemOrder);
			if (this.ReadItemMethod != null)
				args.Add("ReadItemMethod=\"" + this.ReadItemMethod + "\"");
			if (this.WriteItemMethod != null)
				args.Add("WriteItemMethod=\"" + this.WriteItemMethod + "\"");
			if (this.GetItemSizeMethod != null)
				args.Add("GetItemSizeMethod=\"" + this.GetItemSizeMethod + "\"");
			return "[BinBlock(" + String.Join(", ", args) + ")]";
		}
	}
}
